#ifndef __VertexIndexData_H__
#define __VertexIndexData_H__

#include "HardwareVertexBuffer.h"
#include "HardwareIndexBuffer.h"

namespace PVM
{
	typedef vector<HardwareBuffer::Usage> BufferUsageList;
	class VertexData
	{
	private:
		VertexData(const VertexData& rhs);
		VertexData& operator=(const VertexData& rhs)
		
		HardwareBufferManagerBase* mMgr;
	public:
		VertexData(HardwareBufferManagerBase* mgr = 0);
		VertexData(VertexDeclaration* dcl, VertexBufferBinding* bind);
		~VertexData();
		
		VertexDeclaration* vertexDeclaration;
		VertexBufferBinding* vertexBufferBinding;
		bool mDeleteDclBinding;
		size_t vertexStart;
		size_t vertexCount;
		
		struct HardwareAnimationData
		{
			unsigned short targetBufferIndex;
			float parametric;
		};
		
		typedef vector<HardwareAnimationData> HardwareAnimationDataList;
		HardwareAnimationDataList hwAnimationDataList;
		size_t hwAnimDataItemsUsed;
		
		VertexData* clone(bool copyData = true, HardwareBufferManagerBase* mgr = 0) const;
		
		void prepareForShadowVolume(void);
		HardwareVertexBufferSharedPtr hardwareShadowVolWBuffer;
		
		void reorganiseBuffers(VertexDeclaration* newDeclaration, const BufferUsageList& bufferUsage,
							   HardwareBufferManagerBase* mgr = 0);
		
		void reorganiseBuffers(VertexDeclaration* newDeclaration, HardwareBufferManagerBase* mgr = 0);
		
		void closeGapsInBindings(void);
		
		void removeUnusedBuffers(void);
		
		void convertPackedColour(VertexElementType srcType, VertexElementType destType);
		
		ushort allocateHardwareAnimationElements(ushort count, bool animateNormals);
	};
	
	class IndexData
	{
	protected:
		IndexData(const IndexData& rhs);
		IndexData& operator=(const IndexData& rhs);
	public:
		IndexData();
		~IndexData();
		HardwareIndexBufferSharedPtr indexBuffer;
		
		size_t indexStart;
		size_t indexCount;
		
		IndexData* clone(bool copyData = true, HardwareBufferManagerBase* mgr = 0) const;
		
		void optimiseVertexCacheTriList(void);
	};
	
	class VertexCacheProfiler
	{
	public:
		enum CacheType
		{
			FIFO,
			LRU
		};
		
		VertexCacheProfiler(unsigned int cachesize = 16, CacheType cachetype = FIFO)
		: size(cachesize), type(cachetype), tail(0), buffersize(0), hit(0), miss(0)
		{
			cache = new uint32[size];
		}
		
		~VertexCacheProfiler()
		{
			delete[] cache;
		}
		
		void profile(const HardwareIndexBufferSharedPtr& indexBuffer);
		void reset() {hit = 0; miss = 0; tail = 0; buffersize = 0;}
		void flush() {tail = 0; buffersize = 0;}
		
		unsigned int getHits() {return hit;}
		unsigned int getMisses() {return miss;}
		unsigned int getSize() {return size;}
		
	private:
		unsigned int size;
		uint32* cache;
		CacheType type;
		
		unsigned int tail, buffersize;
		unsigned int hit, miss;
		
		bool inCache(unsigned int index);
	};
}

#endif
